﻿using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

public class EncodingInformation
{
    [MenuItem("Tools/LuaScriptToUTF8", false, 30)]
    public static void ChangeLuaFileToUTF8NoBOM()
    {
        Encoding encoding = new UTF8Encoding(false);
        EncodingInformation ei = new EncodingInformation();

        string luaPath = Application.dataPath + "/Lua/";
        string[] files = Directory.GetFiles(luaPath, "*.lua", SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            string fileName = files[i];
            if (File.Exists(fileName))
            {
                try
                {
                    FileStream fs = new FileStream(fileName, FileMode.Open);
                    string text = string.Empty; bool UFT8WithNoBom = false;
                    Encoding targetEncoding = ei.GetType(fs, out UFT8WithNoBom);
                    fs.Close(); string title = "";

                    //将非UTF8或者UTF8带BOM的都转为UTF8不带BOM
                    if (targetEncoding != Encoding.UTF8 || !UFT8WithNoBom)
                    {
                        if (targetEncoding != Encoding.UTF8)
                        {
                            title = "非UTF8编码";
                        }
                        else
                        {
                            title = "UTF8 带BOM";
                        }
                        Debug.Log(fileName + " " + title);
                        EditorUtility.DisplayProgressBar(title, fileName, i * 1.0f / files.Length);
                        using (StreamReader sr = new StreamReader(fileName, targetEncoding))
                        {
                            text = sr.ReadToEnd();
                        }

                        using (StreamWriter sw = new StreamWriter(fileName, false, encoding))
                        {
                            sw.Write(text);
                        }
                    }
                    else
                    {
                        title = "UFT8";
                        EditorUtility.DisplayProgressBar(title, fileName, i * 1.0f / files.Length);
                    }
                }
                catch (Exception e)
                {
                    Debug.Log(e.ToString());
                }
            }
        }
        EditorUtility.ClearProgressBar();
    }

    /// <summary>  
    /// 通过给定的文件流，判断文件的编码类型  
    /// </summary>  
    /// <param name="fs">文件流</param>  
    /// <returns>文件的编码类型</returns>  
    public Encoding GetType(FileStream fs, out bool utf8WithBom)
    {
        int i; utf8WithBom = false;
        Encoding reVal = Encoding.Default;

        int.TryParse(fs.Length.ToString(), out i);
        var br = new BinaryReader(fs, reVal);
        byte[] bytes = br.ReadBytes(i); 

        if (IsUTF8Bytes(bytes) || (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF))
        {
            reVal = Encoding.UTF8;
            utf8WithBom = IsUTF8Bytes(bytes);
        }
        else if (bytes[0] == 0xFE && bytes[1] == 0xFF && bytes[2] == 0x00)
        {
            reVal = Encoding.BigEndianUnicode;
        }
        else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0x41)
        {
            reVal = Encoding.Unicode;
        }
        br.Close(); return reVal;
    }

    /// <summary>  
    /// 判断是否是不带 BOM 的 UTF8 格式  
    /// </summary>  
    /// <param name="data"></param>  
    /// <returns>true:不带BOM  false:带BOM</returns>  
    bool IsUTF8Bytes(byte[] data)
    {
        int charByteCounter = 1; byte curByte;
        for (int i = 0; i < data.Length; i++)
        {
            curByte = data[i];
            if (charByteCounter == 1)
            {
                if (curByte >= 0x80)
                {
                    //判断当前  
                    while (((curByte <<= 1) & 0x80) != 0)
                    {
                        charByteCounter++;
                    }
                    //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X　  
                    if (charByteCounter == 1 || charByteCounter > 6)
                    {
                        return false;
                    }
                }
            }
            else
            {
                //若是UTF-8 此时第一位必须为1  
                if ((curByte & 0xC0) != 0x80)
                {
                    return false;
                }
                charByteCounter--;
            }
        }
        if (charByteCounter > 1)
        {
            throw new Exception("非预期的byte格式");
        }
        return true;
    }
}